﻿using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace SimpleNugetServer.Models
{
    public class NuspecVersionCompare : IComparer<Nuspec>
    {
        private static Regex regex = new Regex(@"(?i)^(?<ver>\d+(\.\d+)*)(\-(?<pre>alpha|beta|rc)(?<pre_ver>\d*))?(\-build(?<build_ver>\d+))?$");
        public static NuspecVersionCompare Instance { get; private set; } = new NuspecVersionCompare();

        public int Compare(Nuspec x, Nuspec y)
        {
            // TODO 需要处理以下格式
            // microsoft.dotnet.projectmodel.1.0.0-rc3-1-003177
            // Microsoft.DotNet.ProjectModel.1.0.0-rc3-003121.nupkg
            // microsoft.aspnet.authentication.cookies.1.0.0-rc1-final.nupkg
            // fluentvalidation.6.4.0-rc4.nupkg
            // xunit.extensibility.execution.2.2.0-rc4-build3536.nupkg
            // internal.aspnetcore.sdk.1.0.1-rc2-15179.nupkg
            // microsoft.entityframeworkcore.tools.1.1.0-msbuild3-final
            // moq.4.6.36-alpha.nupkg
            // sixlabors.fonts.0.1.0-alpha0010.nupkg
            // SkiaSharp.1.56.1-beta.nupkg
            // stylecop.analyzers.1.1.0-beta001.nupkg
            // stylecop.msbuild.5.0.0-beta01.nupkg
            // NuGet.Packaging.3.5.0-beta2-1484.nupkg

            // 格式可以是 2.2.0-rc1-build3536
            // 格式可以是 2.2.0-alpha1-build3536

            // 通过版本号判断.并且使用反序，即使用y与x进行比较。

            var mtX = regex.Match(x.Metadata.Version);
            var mtY = regex.Match(y.Metadata.Version);
            if (mtX.Success && mtY.Success)
            {
                // 比较大版本
                Version verX = new Version(mtX.Groups["ver"].Value);
                Version verY = new Version(mtY.Groups["ver"].Value);
                var v = verY.CompareTo(verX);
                if (v != 0) return v;

                // 比较 alpha, beta, rc
                var preArray = new List<string>(new string[] { "alpha", "beta", "rc", "" });
                var preX = preArray.IndexOf(mtX.Groups["pre"].Value.ToLower());
                var preY = preArray.IndexOf(mtY.Groups["pre"].Value.ToLower());
                v = preY.CompareTo(preX);
                if (v != 0) return v;

                var pre_verX = string.IsNullOrWhiteSpace(mtX.Groups["pre_ver"].Value) ? 0 : int.Parse(mtX.Groups["pre_ver"].Value);
                var pre_verY = string.IsNullOrWhiteSpace(mtY.Groups["pre_ver"].Value) ? 0 : int.Parse(mtY.Groups["pre_ver"].Value);
                v = pre_verY.CompareTo(pre_verX);
                if (v != 0) return v;

                var build_verX = string.IsNullOrWhiteSpace(mtX.Groups["build_ver"].Value) ? 0 : int.Parse(mtX.Groups["build_ver"].Value);
                var build_verY = string.IsNullOrWhiteSpace(mtY.Groups["build_ver"].Value) ? 0 : int.Parse(mtY.Groups["build_ver"].Value);

                v = build_verY.CompareTo(build_verX);
                return v;
            }
            else
            {
                return string.Compare(y.Metadata.Version, x.Metadata.Version);
            }
        }
    }
}
